package controller.grid;

import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.LineArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.TransparencyAttributes;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Tuple3d;
import javax.vecmath.Vector3f;

import math.Spherical;

public class Grid extends BranchGroup {
	
	private TransformGroup posTG = new TransformGroup();
	private TransformGroup rotTG = new TransformGroup();
	
	private Spherical orientation = new Spherical(0, 0);
	
	private Point3d position = new Point3d(0, 0, 0);
	private Color3f color = new Color3f(1, 1, 1);
	
	public Grid(Point3d position, Spherical orientation, Color3f color) {
		this.setPos(position);
		this.setRotation(orientation);
		this.setColor(color);
		this.setCapability(BranchGroup.ALLOW_DETACH);
		
		posTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		rotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
		
		TransparencyAttributes transAtri = new TransparencyAttributes();
		transAtri.setTransparency(0.4f);
		transAtri.setTransparencyMode(TransparencyAttributes.BLENDED);
		
		Appearance app = new Appearance();
		app.setColoringAttributes(new ColoringAttributes(color, ColoringAttributes.SHADE_FLAT));
		app.setTransparencyAttributes(transAtri);
		
		Shape3D gridGeo = this.createGeometry(5);
		gridGeo.setAppearance(app);
		
		rotTG.addChild(gridGeo);
		posTG.addChild(rotTG);
		this.addChild(posTG);
	}
	
	public void setPos(Tuple3d pos) {
		this.position.set(pos);
		
		Transform3D transform = new Transform3D();
		transform.setTranslation(new Vector3f(pos));
		
		posTG.setTransform(transform);
	}
	
	public Point3d getPos() {
		return position;
	}
	
	public void setRotation(Spherical orientation) {
		this.orientation = orientation;
		
		Transform3D zTransform = new Transform3D();
		zTransform.rotZ(this.orientation.getZ());
		Transform3D yTransform = new Transform3D();
		yTransform.rotY(this.orientation.getY());
		
		zTransform.mul(yTransform);
		
		rotTG.setTransform(zTransform);
	}
	
	protected Shape3D createGeometry(int grid) {
		Shape3D gridShape = new Shape3D();
		
		gridShape.addGeometry(createXLines(25));
		gridShape.addGeometry(createYLines(25));
		
		return gridShape;
	}
	
	public void setColor(Color3f color) {
		this.color  = color;
	}
	
	public Color3f getColor() {
		return color;
	}
	
	private LineArray createXLines(int grid) {
		LineArray la = new LineArray(grid * (grid*2 -2) , LineArray.COORDINATES);
			
		double x = -(grid -1) / 2.0;
		double y = -(grid -1) / 2.0;
		
		int coord = 0;
		
		for (int l = 0; l < grid; l++) {
			for (int r = 0; r < grid -1; r++) {
				Point3d p = new Point3d(x+l, y+r, 0);
				Point3d p2 = new Point3d(x+l, y+r + 1, 0);

				la.setCoordinate(coord++, p);
				la.setCoordinate(coord++, p2);
			}
		}
		return la;
	}
	
	private LineArray createYLines(int grid) {
		LineArray la = new LineArray(grid * (grid*2 -2) , LineArray.COORDINATES);

		double x = -(grid -1) / 2.0;
		double y = -(grid -1) / 2.0;
		
		int coord = 0;
		
		for (int l = 0; l < grid; l++) {
			for (int r = 0; r < grid -1; r++) {
				Point3d p = new Point3d(x+r, y+l, 0);
				Point3d p2 = new Point3d(x+r + 1, y+l, 0);
						
				la.setCoordinate(coord++, p);
				la.setCoordinate(coord++, p2);
			}
		}
		return la;
	}
}
